package com.kaili.db.service.impl;

import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.kaili.pojo.dto.arrive.*;
import com.kaili.client.service.ILoginUserInfoService;
import com.kaili.common.OperationType;
import com.kaili.common.stock.StockInfoBean;
import com.kaili.common.util.LoginDetailUtils;
import com.kaili.db.mapper.HsOptArriveMapper;
import com.kaili.db.service.*;
import com.kaili.pojo.entity.*;
import com.kaili.pojo.vo.ArriveEwbVO;
import com.kaili.pojo.vo.ExportArriveVO;
import com.kaili.pojo.vo.StowageVO;
import com.kaili.common.exception.BaseExcept;
import com.kaili.except.ResponseStatus;
import com.kaili.utils.DateUtils;
import com.kaili.common.util.SnowflakeIdFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.*;

import static com.kaili.except.ResponseStatus.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cgm
 * @since 2018-05-08
 */
@Service
@Transactional
public class HsOptArriveServiceImpl extends ServiceImpl<HsOptArriveMapper, HsOptArrive> implements IHsOptArriveService {

    @Autowired
    private IHsOptArriveService optArriveService;

    @Autowired
    private ILoginUserInfoService login;
    @Autowired
    private IHsOptQueryService queryService;
    @Autowired
    private IHsEwbSubStockService stockService;

    @Autowired
    private HsOptArriveMapper optArriveMapper;

    @Autowired
    private IHsEwbsStowageSubService ewbsStowageSubService;

    private static final Logger logger = LogManager.getLogger();

    @Override
    public boolean insertBatch(List<HsOptArrive> list){
        baseMapper.insertBatch(list);
        return true;
    }

    /**
     * 查询所有配载单
     *
     * @param page
     * @param search
     * @return
     * @throws Exception
     */
    @Override
    public Page<StowageVO> queryStowageArrive(Page<StowageVO> page, Map search) throws Exception {
        return page.setRecords(baseMapper.queryStowageArrive(page, search));
    }

    @Override
    public List<StowageVO> queryStowageArriveList(Map search) throws Exception {
        return baseMapper.queryStowageArrive(search);
    }

    /**
     * 查询配载单详情
     *
     * @param page
     * @param search
     * @return
     * @throws Exception
     */
    @Override
    public Page<ArriveEwbVO> queryArriveEwb(Page<ArriveEwbVO> page, Map search) throws Exception {


        List<ArriveEwbVO> list = baseMapper.queryArriveEwb(page, search);
        for (ArriveEwbVO arriveEwbVO:list){
            Map<String,Object> map=new HashMap<String,Object>();
            map.put("ewb_no",arriveEwbVO.getEwbNo());
            map.put("operation_id",search.get("operationId"));
            List<HsEwbsStowageSub> subs = ewbsStowageSubService.selectByMap(map);
            arriveEwbVO.setSubList(subs);
        }
        return page.setRecords(list);
    }

    /**
     * 配载单到件服务
     *
     * @param stowageDTOS
     * @return
     * @throws Exception
     */
    @Transactional
    @Override
    public Boolean doStowageArriveConfirm(List<ArriveStowageDTO> stowageDTOS) throws BaseExcept {
        List<String> exsitsList = new ArrayList<>();//记录运单号是否已做库存调整
        Integer currentEmployeeId = LoginDetailUtils.getCurrentEmployeeId();//当前操作人
        for (ArriveStowageDTO stowageDTO : stowageDTOS) {
            Map<String, Object> search = new HashMap<>();
            search.put("operationId", stowageDTO.getOperationId());
            //获取配载单的信息
            StowageVO stowage = baseMapper.getStowageByStowageNo(search);
            if (stowage == null) {
                throw new BaseExcept(ResponseStatus.STOWAGE_NOT_EWB_NO);
            }
            //配载单状态0-未发/1-在途/2-到件
            if (1L == stowage.getStatus()) {
                //进行配载单详情修改,获取配载单详情表中的托运单集合
                List<ArriveEwbVO> arriveEwbVOList = baseMapper.queryArriveEwb(search);
                List<HsOptArrive> arrives = new ArrayList<>();
                //循环遍历配载单详情
                List<HsOptQuery> queryList = new ArrayList<>();
                for (ArriveEwbVO optArrive : arriveEwbVOList) {
                    if ("2".equals(optArrive.getStatus())) {
                        continue;
                    }
                    HsEwbsStowageDetail ewbsStowageDetail = new HsEwbsStowageDetail();
                    ewbsStowageDetail.setOperationId(stowage.getOperationId());
                    ewbsStowageDetail.setEwbNo(optArrive.getEwbNo());
                    ewbsStowageDetail.setInWeight(optArrive.getOutWeight());
                    ewbsStowageDetail.setInVol(optArrive.getOutVol());
                    ewbsStowageDetail.setInPiece(optArrive.getOutPiece());
                    ewbsStowageDetail.setInConfirmBy(currentEmployeeId);
                    ewbsStowageDetail.setInConfirmTime(DateUtils.getNowDate());
                    ewbsStowageDetail.setStatus(2);//配载单状态(0-未发 1- 在途 2-已到)
                    baseMapper.updateStowageDetailArrive(ewbsStowageDetail);

                    HsOptArrive arrive = new HsOptArrive();
                    arrive.setOperationId(SnowflakeIdFactory.getNextId());
                    arrive.setEwbNo(optArrive.getEwbNo());
                    arrive.setSiteId(login.getLoginSiteId());//操作站点ID
                    arrive.setScanTime(new Date());
                    arrive.setPriorSiteId(stowage.getSendSiteId());
                    arrive.setDestinationId(optArrive.getDestinationId());
                    arrive.setScanSourceId(118);
                    arrive.setDeviceCode("C");
                    arrive.setPiece(optArrive.getOutPiece());
                    arrive.setVol(optArrive.getVol());
                    arrive.setWeight(optArrive.getOutWeight());
                    arrive.setCreatedBy(currentEmployeeId);
                    arrive.setCreatedTime(DateUtils.getNowDate());
                    arrive.setSourceType(stowageDTO.getSourceType());
                    //optArriveService.insert(arrive);
                    arrives.add(arrive);
                    //生成运单跟踪
                    HsOptQuery query = new HsOptQuery();
                    query.setEwbNo(arrive.getEwbNo());
                    query.setStep(OperationType.ARRIVING);//1开单  2配载  3发车  4在途  5到车  6派件  7签收
                    query.setOperationTime(DateUtils.getNowDate());
                    query.setOperationId(String.valueOf(SnowflakeIdFactory.getNextId()));
                    query.setOperationSiteId(login.getLoginSiteId());
                    query.setOperator(login.getLoginUserId());
                    queryList.add(query);

                    if (!exsitsList.contains(arrive.getEwbNo())) {
                        exsitsList.add(arrive.getEwbNo());
                        StockInfoBean stock = new StockInfoBean();
                        stock.setSiteId(login.getLoginSiteId());
                        stock.setEwbNo(arrive.getEwbNo());
                        stock.setPreSiteId(arrive.getPriorSiteId());
                        stock.setSize(arrive.getPiece());
                        //生成相关库存
                        logger.info("pdx-siteId=" + stock.getSiteId());
                        stockService.arriveEwbByBs(stock, true);
                    }
                }
                optArriveService.insertBatch(arrives);
                queryService.insertBatch(queryList);
                //如果在途中的运单数量不存在,则修改配载单状态为 到货
                if (baseMapper.queryUnArriveEwbCount(stowageDTO.getOperationId()) <= 0) {
                    //修改配载表
                    updateArriveStowageConfirm(stowageDTO.getOperationId());
                }
                return true;
            } else //                throw new BaseExcept(ResponseStatus.STOWAGE_ARRIVED);
                return 2L == stowage.getStatus();
        }
        return true;
    }

    /**
     * 根据配载单号获取配载单
     *
     * @param search
     * @return
     * @throws Exception
     */
    @Override
    public StowageVO getStowageByStowageNo(Map search) throws Exception {
        return baseMapper.getStowageByStowageNo(search);
    }

    /**
     * 运单到件(BS/APP共用)
     *
     * @throws BaseExcept
     */
    @Transactional
    @Override
    public Boolean doEwbArriveConfirm(ArriveAddDTO arrive) throws BaseExcept {
        List<HsOptArrive> lst = arrive.getList();
        if (lst == null || lst.size() < 1) {
            throw new BaseExcept(EWB_EMPTY);
        }
        Integer currentEmployeeId = LoginDetailUtils.getCurrentEmployeeId();//当前操作人
        String operationId = arrive.getOperationId();
        Map<String, Object> param = new HashMap<>();
        param.put("operationId", operationId);
        //获取配载单状态
        StowageVO stowageVO = baseMapper.getStowageByStowageNo(param);
        if (stowageVO == null) {
            throw new BaseExcept(STOWAGE_ADD_DUPLICATE);
        }
        if (stowageVO.getStatus() == 2) {
            return true;
//            throw new BaseExcept(RESPONSE_CHECK_ERROR);
        }

        List<HsOptArrive> arrives = new ArrayList<>();
        List<HsOptQuery> queryList = new ArrayList<>();
        HsEwbsStowageDetail ewbsStowageDetail = null;

        Map<String, Object> search = new HashMap<>();
        search.put("operationId", operationId);
        ArriveEwbVO arriveEwbVO = null;
        List<ArriveEwbVO> arriveEwbVOList = null;
        //循环新增到件表
        for (int i = 0; i < lst.size(); i++) {
            //配载单详情修改
            HsOptArrive optArrive = lst.get(i);

            search.put("ewbNo", optArrive.getEwbNo());
            arriveEwbVOList = baseMapper.queryArriveEwb(search);
            if(null != arriveEwbVOList && arriveEwbVOList.size()>0){
                arriveEwbVO = arriveEwbVOList.get(0);
            }
            if("2".equals(arriveEwbVO.getStatus())){
                continue;
//                throw new BaseExcept(ARRIVE_CONFIRM_REPEAT);
            }
            optArrive.setOperationId(SnowflakeIdFactory.getNextId());
            optArrive.setEwbNo(optArrive.getEwbNo());
            optArrive.setSiteId(login.getLoginSiteId());//操作站点ID
            optArrive.setScanTime(new Date());
            optArrive.setDestinationId(arriveEwbVO.getDestinationId());
            optArrive.setScanSourceId(118);
            optArrive.setDeviceCode("C");
            optArrive.setPiece(arriveEwbVO.getOutPiece());
            optArrive.setVol(arriveEwbVO.getVol());
            optArrive.setWeight(arriveEwbVO.getOutWeight());
            optArrive.setCreatedBy(currentEmployeeId);
            optArrive.setCreatedTime(DateUtils.getNowDate());
            optArrive.setSourceType(arrive.getSourceType());
            arrives.add(optArrive);

            /******************************配载单表进行操作*******************************************/
            ewbsStowageDetail = new HsEwbsStowageDetail();
            ewbsStowageDetail.setOperationId(operationId);
            ewbsStowageDetail.setEwbNo(arriveEwbVO.getEwbNo());
            ewbsStowageDetail.setInWeight(arriveEwbVO.getOutWeight());
            ewbsStowageDetail.setInVol(arriveEwbVO.getOutVol());
            ewbsStowageDetail.setInPiece(arriveEwbVO.getOutPiece());
            ewbsStowageDetail.setInConfirmBy(currentEmployeeId);
            ewbsStowageDetail.setInConfirmTime(DateUtils.getNowDate());
            ewbsStowageDetail.setInDeviceCode(arrive.getInDeviceCode());//进站设备编号
            ewbsStowageDetail.setInScanSourceId(arrive.getInScanSourceId());//进站数据来源
            ewbsStowageDetail.setStatus(2);//配载单状态(0-未发 1- 在途 2-已到)
            //修改配载单详情表
            baseMapper.updateStowageDetailArrive(ewbsStowageDetail);
            /*********************对到件表、运单跟踪进行操作（库存）*******************************************/

            //生成运单跟踪
            HsOptQuery query = new HsOptQuery();
            query.setEwbNo(arriveEwbVO.getEwbNo());
            query.setStep(OperationType.ARRIVING);//1开单  2配载  3发车  4在途  5到车  6派件  7签收
            query.setOperationTime(DateUtils.getNowDate());
            query.setOperationId(String.valueOf(SnowflakeIdFactory.getNextId()));
            query.setOperationSiteId(login.getLoginSiteId());
            query.setOperator(login.getLoginUserId());
            queryList.add(query);

            //托运开单添加子单库存
            StockInfoBean bean = new StockInfoBean();
            bean.setEwbNo(arriveEwbVO.getEwbNo());
            bean.setSiteId(login.getLoginSiteId());
            bean.setSize(arriveEwbVO.getOutPiece());
            bean.setPreSiteId(stowageVO.getSendSiteId());
            stockService.arriveEwbByBs(bean,true);
        }
        if(arrives.size()>0){
            optArriveService.insertBatch(arrives);
        }
        if(queryList.size()>0){
            //新增运单跟踪
            queryService.insertBatch(queryList);
        }
        //如果在途中的运单数量不存在,则修改配载单状态为 到货
        if(baseMapper.queryUnArriveEwbCount(operationId)<=0){
            //修改配载表
            updateArriveStowageConfirm(operationId);
        }

        return true;
    }

    /**
     * 配载单详情到件
     *
     * @param ewbsStowageDetail
     * @return
     * @throws Exception
     */
    @Override
    public Boolean updateStowageDetailArrive(HsEwbsStowageDetail ewbsStowageDetail) throws Exception {
        if (0 != baseMapper.updateStowageDetailArrive(ewbsStowageDetail)) {
            return true;
        }
        return false;
    }

    @Override
    public int updatePrintStowage(ArrivePrintNumberDTO printNumberDTO) throws BaseExcept {
        if (printNumberDTO.getStowageNo() == null) {
            return -1;
        }
        return baseMapper.updataPrintStowage(printNumberDTO);
    }

    @Override
    public List<ExportArriveVO> exportArriveQueryList(Map map) throws BaseExcept {
        return baseMapper.exportArriveQueryList(map);
    }

    /**
     * 取消托运单到件
     *
     * @param req
     * @return
     * @throws BaseExcept
     */
    @Override
    public Boolean doStowageArriveCancel(List<ArriveCancelDTO> req) throws BaseExcept {
        if (req == null || req.isEmpty()) {
            throw new BaseExcept(ResponseStatus.ARRIVE_CANCEL_EWB);
        }
        HsEwbsStowageDetail ewbsStowageDetail ;
        for (int i = 0; i < req.size(); i++) {
            ArriveCancelDTO bean = req.get(i);
            String operationId = bean.getOperationId();
            /*************************修改配载表*********************************/
            updateArriveStowageCancel(operationId);

            Map<String, Object> param = new HashMap<>();
            param.put("operationId", operationId);
            List<ArriveEwbVO> lst = baseMapper.queryArriveEwb(param);
            //循环移除库存
            List<String> exsitsList = new ArrayList<>();//记录运单号是否已做库存调整
            for (int j = 0; j < lst.size(); j++) {
                //配载单详情修改
                ArriveEwbVO optArrive = lst.get(j);

                if("0".equals(optArrive.getStatus()) || "1".equals(optArrive.getStatus())){
                    continue;
                }

                //修改配载明细状态为 在途中
                ewbsStowageDetail = new HsEwbsStowageDetail();
                ewbsStowageDetail.setOperationId(operationId);
                ewbsStowageDetail.setStatus(1);
                ewbsStowageDetail.setInPiece(0);
                ewbsStowageDetail.setInWeight(new BigDecimal(0));
                ewbsStowageDetail.setInVol(new BigDecimal(0));
                baseMapper.updateStowageDetailArrive(ewbsStowageDetail);

                if(!exsitsList.contains(optArrive.getEwbNo())){
                    exsitsList.add(optArrive.getEwbNo());
                    //用于库存调整
                    StockInfoBean stock = new StockInfoBean();
                    stock.setSiteId(login.getLoginSiteId());
                    stock.setEwbNo(optArrive.getEwbNo());
                    stock.setPreSiteId(optArrive.getPriorSiteId());
                    stock.setSize(optArrive.getOutPiece());
                    stockService.arriveEwbByBs(stock,false);
                }
            }
        }
        return true;
    }

    /**
     * 配载单部分到件取消
     * 1、配载单到件重量、体积、件数等改变
     * 2、配载单详情表中相应的运单删除
     * 3、库存表中的相应运单为在途（非在库）
     * 4、运单跟踪(目前没修改)
     *
     * @param arriveCancelDTO
     * @return
     * @throws BaseExcept
     */
    @Override
    public Boolean doEwbArriveCanCel(ArriveCancelDTO arriveCancelDTO) throws BaseExcept {
        String operationId = arriveCancelDTO.getOperationId();

        // 1.修改配载单未在途中
        updateArriveStowageCancel(operationId);

        Map<String, Object> param = new HashMap<>();
        param.put("operationId", operationId);
        param.put("ewbList", arriveCancelDTO.getEwbNos());
        List<ArriveEwbVO> lst = baseMapper.queryArriveEwb(param);
        for (ArriveEwbVO optArrive : lst) {
            if ("0".equals(optArrive.getStatus()) || "1".equals(optArrive.getStatus())) {
                continue;
            }
            // 2.修改运单状态为在途中
            HsEwbsStowageDetail ewbsStowageDetail = new HsEwbsStowageDetail();
            ewbsStowageDetail.setOperationId(operationId);
            ewbsStowageDetail.setEwbNo(optArrive.getEwbNo());
            ewbsStowageDetail.setStatus(1);
            ewbsStowageDetail.setInPiece(0);
            ewbsStowageDetail.setInWeight(new BigDecimal(0));
            ewbsStowageDetail.setInVol(new BigDecimal(0));
            baseMapper.updateStowageDetailArrive(ewbsStowageDetail);

            // 3.处理库存
            StockInfoBean stock = new StockInfoBean();
            stock.setSiteId(login.getLoginSiteId());
            stock.setEwbNo(optArrive.getEwbNo());
            stock.setPreSiteId(optArrive.getPriorSiteId());
            stock.setSize(optArrive.getOutPiece());
            stockService.arriveEwbByBs(stock, false);
        }

        return true;
    }

    @Override
    public List<ArriveEwbVO> queryPrintArriveEwb(Map map) throws BaseExcept {
        return optArriveMapper.queryPrintArriveEwb(map);
    }

    /**
     * 到车-修改配载单
     * @param operationId
     */
    private void updateArriveStowageConfirm(String operationId){
        Integer currentEmployeeId = LoginDetailUtils.getCurrentEmployeeId();//当前操作人

        HsEwbsStowage stowage = new HsEwbsStowage();
        stowage.setOperationId(operationId);
        stowage.setIsArrive(1);
        stowage.setStatus(2);
        stowage.setCarArriveTime(DateUtils.getNowDate());//配载单到车时间
        stowage.setInConfirmBy(currentEmployeeId);
        stowage.setInConfirmTime(DateUtils.getNowDate());//进站确认时间
        baseMapper.updateArriveStowage(stowage);
    }

    /**
     * 取消到车-修改配载单
     * @param operationId
     */
    private void updateArriveStowageCancel(String operationId){
        HsEwbsStowage stowage = new HsEwbsStowage();
        stowage.setOperationId(operationId);
        stowage.setIsArrive(0);
        stowage.setStatus(1);//配载单状态(0-未发 1- 在途 2-已到)
        baseMapper.updateArriveStowage(stowage);
    }
}
